package de.fhd.pms;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.Locale;
import java.io.FileOutputStream;

import javax.servlet.http.HttpServlet;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import de.fhd.pms.dto.RechnungDTO;
import de.fhd.pms.model.Automobil;
import de.fhd.pms.model.Fahrt;
import de.fhd.pms.model.Standort;
import de.fhd.pms.model.Teilnehmer;

/**
 * Klasse zur Rechnungsgenerierung von absolvierten Fahrten.
 * 
 * @return Rechnung als PDF-Datei mit typischem Aufbau:
 * 
 * <li>Rechnungskopf
 * <li>Rechnungsinformationen mit Positionen
 * <li>Rechnungsfuß mit Anschrift, Bankdaten, etc.
 * 
 * @see Klasse Invoice.java
 * @author Martin Schmid
 * @author Florian Schachner
 */
public class Rechnung{
	
/**
* Generiert die Rechnung unter Verwendung von itext-Bibliotheken.
* <p></p>
* Mithilfe des Konstruktors der Klasse {@link Rechnung} werden Rechnungen im PDF-Format generiert.
* Hier werden vorab allgemeine Einstellungen festgelegt und die gefahrenen Kilometer berechnet.
* Anschließend wird mithilfe seperater Sektionen ({@link Paragraph}) die Struktur des PDFs-Dokumentes aufgebaut.
* Die Zusammensetzung des Dokumentes erfolgt am Ende der Methode. 
* 
* @param re Übergabe eines Objekts vom Typ {@link RechnungDTO}, welches alle notwendigen Daten im String-Format enthält.
* @author Martin Schmid
* @author Florian Schachner
*/	
	//Konstruktor
	public Rechnung(RechnungDTO re) {		    	
		String crlf = "\r\n"; //zum Einfügen eventuelle Leerzeilen bzw. Absätze
	
		//Allgemeine Daten
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date()); //Aktuelles Tagesdatum
	
		//Aufbereitung von Beträgen für Deutsches Format
		String waers = Currency.getInstance(Locale.GERMANY).getCurrencyCode();
		DecimalFormat de = new DecimalFormat("#0.00" , new DecimalFormatSymbols(Locale.GERMANY));

		double flPreisJeKilometer = 1.28;
		double flMwstSatz = 19.00;
				
		//Pfad für Rechnungserstellung
		String FILE = "c:/carsharing/Rechnungen/" + cal.get(Calendar.YEAR) + "-" + re.getFahrtid() + "_" + re.getName() + ".pdf"; //Pfad der Ablage der PDF-Datei
		
		//Zahlungsbedingungen
		String strZahlungsbedingungen = "Der Rechnungsbetrag ist innerhalb von zwei Wochen nach dem oben " +
				"genannten Rechnungsdatum auf untenstehendes Konto ohne Abzüge zu überweisen. " +
				"Andernfalls wird ein dreistufiges Mahnverfahren mit enstprechenden Zinsen " +
				"eingeleitet. Weiteres entnehmen Sie bitte unseren AGBs.";
		
		//Brieffuss
		String strKleingedrucktes = "CarSharing    ||    Edlmairstraße 6 + 8    ||    94469 Deggendorf    ||   Tel.:" +
				" (+49) 991 12345-0    ||    Fax: (+49) 991 123456    ||    Net: www.carSharing.com    ||          Mail: info@carSharing.com" +
				"   ||    UST-ID: DE-987654321    ||    Sparkasse Deggendorf, BLZ: 741 500 00, Konto-Nr.: 123456789";
		
		//Rechnungsnummer und Rechnungsdatum
		int aktJahr = cal.get(Calendar.YEAR); 
		int intRechnungsnummer = 1000 + Integer.valueOf(re.getFahrtid());
		
		//Berechnung der gefahrenen Kilometer sowie Berechnung des Gesamtpreises
		Integer intGefahreneKM = Integer.valueOf(re.getEndekilometer()) - Integer.valueOf(re.getStartkilometer());
		double flGesamtpreisNetto = intGefahreneKM * flPreisJeKilometer;
		double flMwst = flGesamtpreisNetto * flMwstSatz / 100;
		double flGesamtpreisBrutto = flGesamtpreisNetto + flMwst;
		
		//Zusammenstellen der Detailbeschreibung
		String strBeschreibung = "Hersteller: " + re.getHersteller() + "; " + "Modell: " + re.getModell();

		try {
			Document document = new Document();
			PdfWriter.getInstance(document, new FileOutputStream(FILE));
			document.open();

			
			// Textelemente definieren (Schriftart, Schriftgröße, bes. Formatierungen
			Font titleFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD + Font.UNDERLINE); //Titel
			Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 13, Font.BOLD); //Überschriften
			Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 10, Font.BOLD); //Anschriften, Sonstiges
			Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 10, Font.NORMAL); //Texte
			Font smallBold2 = new Font(Font.FontFamily.TIMES_ROMAN, 9); //Details und Informationen zu Positionen
			Font subFont2 = new Font(Font.FontFamily.TIMES_ROMAN, 8, Font.NORMAL); //Kleingedrucktes
			
			//Rechnung
			Paragraph rechnung = new Paragraph();
			
				//Rechnungskopf erzeugen
				Paragraph rechnungskopf = new Paragraph();
				rechnungskopf.add(new Paragraph("CarSharing - Rechnung", titleFont)); //Titel
				addEmptyLine(rechnungskopf, 2);
				
				
				Paragraph rechnungskopf2 = new Paragraph(); //Anschrift
				rechnungskopf2.add(new Paragraph("Herrn/Frau", smallBold)); //Anrede
				rechnungskopf2.add(new Paragraph (re.getName(), smallBold)); //Name
				rechnungskopf2.add(new Paragraph (re.getAnschriftStr(), smallBold)); //Straße und Hausnummer
				rechnungskopf2.add(new Paragraph (re.getAnschriftOrt(), smallBold)); //PLZ und Ort
				addEmptyLine(rechnungskopf2, 1);
				
				Paragraph rechnungskopf3 = new Paragraph();
				rechnungskopf3.add(new Paragraph("Deggendorf, den " + cal.get(Calendar.DAY_OF_MONTH) + "." + cal.get(Calendar.MONTH) + "." + cal.get(Calendar.YEAR), smallBold)); //Ort, Datum
				addEmptyLine(rechnungskopf3, 1);
				
				Paragraph rechnungskopf4 = new Paragraph();
				rechnungskopf4.add(new Paragraph("Rechnungsnummer: " + aktJahr + "-" + intRechnungsnummer, smallBold)); //Rechnungsnummer
				addEmptyLine(rechnungskopf4, 0);
				
				Paragraph rechnungskopf5 = new Paragraph();
				rechnungskopf5.add(new Paragraph("________________________________________________________________________________________________________", smallBold)); //Linie
				addEmptyLine(rechnungskopf5, 1);
				
				//Dokumentenaufbau Rechnungskopf
				addEmptyLine(rechnungskopf, 1);
				document.add(rechnungskopf);
				document.add(rechnungskopf2);
				document.add(rechnungskopf3);
				document.add(rechnungskopf4); 
				document.add(rechnungskopf5);
							
			
				//Rechnungsinformationen erzeugen
				Paragraph rechnungsinformationen = new Paragraph();
				rechnungsinformationen.add(new Paragraph("Rechnungsinformationen", catFont));
				addEmptyLine(rechnungsinformationen, 1);
				
				Paragraph rechnungstext1 = new Paragraph();
				rechnungstext1.add(new Paragraph("Sehr geehrte(r) " + re.getName()  + ",", subFont));
				addEmptyLine(rechnungstext1, 1);
				
				Paragraph rechnungstext2 = new Paragraph();
				rechnungstext2.add(new Paragraph("für Ihren Auftrag bedanken wir uns und erlauben daher folgend" +
						"aufgelistete(n) Leistung(en) in Rechnung zu stellen: ", subFont));
				addEmptyLine(rechnungstext2, 1);
				
				//Positionen erzeugen
				Paragraph rechnungspositionen = new Paragraph();
				rechnungspositionen.add(new Paragraph("Rechnungspositionen", smallBold));
				addEmptyLine(rechnungspositionen, 1);
				
				Paragraph position = new Paragraph();
//				position.add(new Paragraph("Position:                       001", smallBold2));
				position.add(new Paragraph("Kennzeichen:               " + re.getKennzeichen(), smallBold2));
				position.add(new Paragraph("Beschreibung:              " + strBeschreibung, smallBold2));
				position.add(new Paragraph("gefahrene Kilometer:   " + intGefahreneKM, smallBold2));
				position.add(new Paragraph("Preis/km:                      " + de.format(flPreisJeKilometer)  + " " + waers, smallBold2));
				position.add(new Paragraph("Gesamt:                        " + de.format(flGesamtpreisNetto)  + " " + waers, smallBold2));

				
//Alternativ das Ganze als Tabelle:				
				
//				PdfPTable table = new PdfPTable(6);
//				table.setHorizontalAlignment(Element.ALIGN_CENTER);
//				//PdfPCell cell;
//			
//				
//				//table.hasToFitPageCells(true);
//				//table.addCell("Pos.");
//				table.addCell("Auto-Nr.");
//				table.addCell("Bescheibung");
//				table.addCell("gefahrende Kilometer");
//				table.addCell("Preis/km");
//				table.addCell("gesamt");	
//
//				
//				table.addCell("0001");
//				table.addCell(re.getKennzeichen()); //Kennzeichen
//				table.addCell(strBeschreibung); //Beschreibung
//				table.addCell("" + intGefahreneKM); //Gefahrene Kilometer
//				table.addCell("" + flPreisJeKilometer); //Preis pro Kilometer
//				table.addCell("" + flGesamtpreisNetto); //Gesamtpreis
				
				Paragraph platzhalter = new Paragraph();
				platzhalter.add(new Paragraph(""));
				addEmptyLine(platzhalter, 0);
				
				//Rechnungssummen erzeugen
				Paragraph rechnungssummen = new Paragraph();
				rechnungssummen.add(new Paragraph("Rechnungssummen", smallBold));
				addEmptyLine(rechnungssummen, 1);
				
				PdfPTable table2 = new PdfPTable(2);
				table2.setHorizontalAlignment(Element.ALIGN_CENTER);
				//PdfPCell cell;
			
				
				//table.hasToFitPageCells(true);
				table2.addCell("Rechnungsbetrag (netto)");
				table2.addCell(" " + de.format(flGesamtpreisNetto) + " " + waers);
				
				table2.addCell("19 % Umsatzsteuer");
				table2.addCell(" " + de.format(flMwst) + " " + waers);				
				
				table2.addCell("Rechnungsbetrag (brutto)");		
				table2.addCell(" " + de.format(flGesamtpreisBrutto) + " " + waers);
				
				Paragraph platzhalter2 = new Paragraph();
				platzhalter2.add(new Paragraph(""));
				addEmptyLine(platzhalter, 0);
				
				//Zahlungsbedingungen und Sonstiges
				Paragraph zahlung = new Paragraph();
				zahlung.add(new Paragraph("Zahlungsbedingungen und Sonstiges", smallBold));
				addEmptyLine(zahlung, 1);
				
				Paragraph zahlung2 = new Paragraph();
				zahlung2.add(new Paragraph(strZahlungsbedingungen, subFont));
				addEmptyLine(zahlung2, 1);
				
				Paragraph mfg = new Paragraph();
				mfg.add(new Paragraph("Mit freundlichen Grüßen, ", subFont));
				addEmptyLine(mfg, 2);
				
				Paragraph team = new Paragraph();
				team.add(new Paragraph("Ihr CarSharing-Team", subFont));
				addEmptyLine(team, 0);
				
				Paragraph ende = new Paragraph();
				ende.add(new Paragraph("________________________________________________________________________________________________________", smallBold)); //Linie
				addEmptyLine(ende, 0);
				
				Paragraph kleingedrucktes = new Paragraph();
				kleingedrucktes.add(new Paragraph(strKleingedrucktes, subFont2));
				
				
				//Dokumentenaufbau Rechnungskörper
				document.add(rechnungsinformationen);
				document.add(rechnungstext1);
				document.add(rechnungstext2);
				document.add(rechnungspositionen);
				document.add(position); //wenn als Tabelle, dann: document.add(table);
				document.add(platzhalter);
				document.add(rechnungssummen);
				document.add(table2);
				document.add(platzhalter2);
				document.add(zahlung);
				document.add(zahlung2);
				document.add(mfg);
				document.add(team);
				document.add(ende);
				document.add(kleingedrucktes);
					

			//Rechnung als Gesamtes in das PDF-Dokument einbinden
			document.add(rechnung);
			document.newPage();							
			document.close(); 
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
		
/**
* Einfügen von Leerzeilen innerhalb eines Paragraphen des PDF-Dokuments.
* 
* @param paragraph Relevanter {@link Paragraph}, indem Leerzeilen generiert werden.
* @param number Anzahl an einzusetzenden Leerzeilen
* @author Martin Schmid
* @author Florian Schachner
*/
	private static void addEmptyLine(Paragraph paragraph, int number) {
		for (int i = 0; i < number; i++) {
			paragraph.add(new Paragraph(" "));
		}
	}
}